# -*- coding: utf-8 -*-
# @Author: Jerry
# @Date:   2022-02-25 10:44:47
# @Last Modified by:   Jerry
# @Last Modified time: 2022-03-01 15:30:16

# **********
# **********
# OpenCV中的图像处理 » 4_9_1_OpenCV中的轮廓
# http://www.woshicver.com

# **********
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
import os
rootpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
datapath = os.path.join(rootpath,'data')
imgpath = lambda name: os.path.join(datapath,name)

# **********
'''
轮廓：入门
目标
-- 了解轮廓是什么。
-- 学习查找轮廓，绘制轮廓等。
-- 你将看到以下功能：cv.findContours()，cv.drawContours()
什么是轮廓?
-- 轮廓可以简单地解释为连接具有相同颜色或强度的所有连续点（沿边界）的曲线。轮廓是用于形状分析以及对象检测和识别的有用工具。

-- 为了获得更高的准确性，请使用二进制图像。因此，在找到轮廓之前，请应用阈值或canny边缘检测。
-- 从OpenCV 3.2开始，findContours()不再修改源图像。
-- 在OpenCV中，找到轮廓就像从黑色背景中找到白色物体。因此请记住，要找到的对象应该是白色，背景应该是黑色。

cv.findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy
@param image Source, an 8-bit single-channel image.(源图像)
@param mode Contour retrieval mode, see #RetrievalModes(轮廓检索模式)
@param method Contour approximation method, see #ContourApproximationModes(轮廓逼近方法)


cv.findContour()函数中有三个参数，
-- 第一个是源图像，
-- 第二个是轮廓检索模式，
-- 第三个是轮廓逼近方法。
-- 输出等高线和层次结构。
-- 轮廓是图像中所有轮廓的Python列表。
-- 每个单独的轮廓是一个(x,y)坐标的Numpy数组的边界点的对象。

cv.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]]) -> image

'''

# img = cv.imread(imgpath('box_black_white.png'))
img = cv.imread(imgpath('device.png'))
imgray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
cv.imshow('img_gray',imgray)
ret,thresh = cv.threshold(imgray,127,255,0)
contours, hierarchy = cv.findContours(thresh,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
print contours   # 轮廓 边界点的list
print hierarchy  # 层次结构
'''轮廓近似方法
这是 cv.findContours 函数中的第三个参数。它实际上表示什么？
上面我们告诉我们轮廓是强度相同的形状的边界。它存储形状边界的(x,y)坐标。
但是它存储所有坐标吗？这是通过这种轮廓近似方法指定的。
如果传递 cv.CHAIN_APPROX_NONE ，则将存储所有边界点。
但是实际上我们需要所有这些要点吗？
例如，您找到了一条直线的轮廓。您是否需要线上的所有点来代表该线？
不，我们只需要该线的两个端点即可。
这就是 cv.CHAIN_APPROX_SIMPLE 所做的。它删除所有冗余点并压缩轮廓，从而节省内存。'''

img1 = cv.drawContours(img,contours,0,(0,255,0),3) # 颜色：BGR的顺序
cv.imshow('img1',img1)

img2 = cv.drawContours(img,contours,1,(0,255,0),3) # 颜色：BGR的顺序
cv.imshow('img2',img2)

img3 = cv.drawContours(img,contours,2,(0,255,0),3) # 颜色：BGR的顺序
cv.imshow('img3',img3)

img4 = cv.drawContours(img,contours,3,(0,255,0),3) # 颜色：BGR的顺序
cv.imshow('img4',img4)
cnt4 = contours[4]
img41 = cv.drawContours(img,[cnt4],0,(0,255,0),3)
cv.imshow('img41',img41)

imgAll = cv.drawContours(img,contours,-1,(0,255,0),3) # 颜色：BGR的顺序
# 要绘制轮廓，请使用 cv.drawContours 函数。只要有边界点，它也可以用来绘制任何形状。
# 第一个参数是源图像
# 第二个参数是应该作为Python列表传递的轮廓, 即由函数cv.findContours返回的第一个结果
# 第三个参数是轮廓的索引，在绘制单个轮廓时有用。要绘制所有轮廓，请传递-1
# 其余参数是颜色，厚度等等
cv.imshow('img',img)
cv.waitKey(0)



